--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--[[

    长柄专精

    长矛，铲子，金铲子，战斗长矛，草叉，金草叉，三叉戟，火魔杖、冰魔杖、传送法杖，晨星锤，雨伞
    冲锋距离为8格，伤害半径为1格

]]--
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
---
    local MAX_DISTANCE = 8*4     --- 最大长矛冲刺距离
    local SPIKE_COST = TUNING.HUTAO_DEBUGGING_MODE and 1 or TUNING["hutao.Config"].POLEARM_SPIKE_COST or 20       --- 长矛冲刺消耗
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--- 寻找最远可到达的点
    local function GetMaxPassablePoint(start_pt, end_pt)
        return TUNING.HUTAO_FNS:GetMaxPassablePoint(start_pt, end_pt, MAX_DISTANCE,0.2)
    end
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--- 物品检查
    local function IsPolearmEquipping(inst)
        local weapon = inst.replica.combat:GetWeapon() or inst.replica.inventory:GetEquippedItem(EQUIPSLOTS.HANDS)
        if weapon and inst.replica.hutao_com_polearm_mastery:IsSpikeWeapon(weapon.prefab) then
            return true
        end
        return false
    end
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--- 预处理检查函数
    local function Spell_PreCheck(inst)
        if not inst.components.playercontroller:IsEnabled() then
            return false
        end
        if inst:HasTag("playerghost") then
            return false
        end
        if inst.replica.rider and inst.replica.rider:IsRiding() then
            return false
        end
        return true
    end
    local function IsRunning(inst)
        return inst.replica.hutao_com_physical_power:IsRunning() or inst.replica.hutao_com_polearm_mastery:IsRunning()
    end
    local function IsSpellCanCast(inst)
        if not Spell_PreCheck(inst) then
            return false
        end
        if not IsPolearmEquipping(inst) then
            return false
        end
        if not IsRunning(inst) then
            return false
        end
        if inst.replica.hutao_com_physical_power:GetCurrent() < SPIKE_COST then
            return false
        end
        return true
    end
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--- 创建指示器
    local color = Vector3(0/255,255/255,0/255)
    local function CreateIndicator(inst)
        if not (ThePlayer and inst == ThePlayer ) then
            return
        end
        local indicator = SpawnPrefab("hutao_sfx_dotted_arrow_client")
        indicator.AnimState:SetAddColour(color.x, color.y, color.z, 0)
        indicator.AnimState:SetMultColour(color.x, color.y, color.z, 1)
        indicator.AnimState:SetBloomEffectHandle("shaders/anim.ksh")
        indicator:PushEvent("Set",{
            pt = Vector3(ThePlayer.Transform:GetWorldPosition())
        })
        --- 指示器2
        local fx = SpawnPrefab("reticule")
        fx.Transform:SetPosition(ThePlayer.Transform:GetWorldPosition())
        fx.AnimState:SetAddColour(color.x, color.y, color.z, 0)
        fx.AnimState:SetMultColour(color.x, color.y, color.z, 1)
        fx.AnimState:SetBloomEffectHandle("shaders/anim.ksh")
        indicator:ListenForEvent("onremove",function()
            fx:Remove()
        end)
        --- 定时检查指示器
        indicator:DoPeriodicTask(FRAMES*5,function()
            if not IsSpellCanCast(inst) then
                indicator:Remove()
            end
        end)
        --- 刷新器
        TheInput:Hutao_Add_Update_Custom_Fn(indicator,function()
            if indicator.SetRotation then
                local x,y,z = ThePlayer.Transform:GetWorldPosition()
                local mouse_pt = TheInput:GetWorldPosition()
                indicator.Transform:SetPosition(x,y,z)
                local angle = -math.deg(math.atan2(mouse_pt.z - z,mouse_pt.x - x))
                indicator:SetRotation(angle)
                mouse_pt = GetMaxPassablePoint(Vector3(x,y,z),mouse_pt)
                fx.Transform:SetPosition(mouse_pt.x,0,mouse_pt.z)
            else
                indicator:Remove()
            end
        end)
        --- 鼠标监听。
        local mouse_handle = TheInput:AddMouseButtonHandler(function(button,down)
            if down and IsSpellCanCast(inst) and button == MOUSEBUTTON_RIGHT then
                inst.replica.hutao_com_rpc_event:PushEvent("hutao_event.polearm_mastery.spike_start",TheInput:GetWorldPosition())
            end
        end)
        indicator:ListenForEvent("onremove",function()
            mouse_handle:Remove()
        end)
        --- 隐藏/显示
        if not TUNING["hutao.Config"].SPELL_SPIKE_INDICATOR then
            indicator:Hide()
            fx:Hide()
        end
        return indicator
    end
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--- 突刺冲锋+伤害
    local function do_spike_assault_and_damage(inst,tarpos) -- 突刺冲锋+伤害
        -- inst.sg:GoToState("hutao_sg_spurt",{targetpos = tarpos})
        local start_pos = Vector3(inst.Transform:GetWorldPosition())
        local end_pos = Vector3(tarpos.x,0,tarpos.z)
        local end_pos = GetMaxPassablePoint(start_pos,end_pos)
        inst.sg:GoToState("hutao_sg_spurt",{targetpos = end_pos})
        -----------------------------------------------------------------------
        --- 充能。没满能量的突刺，才允许充能。
            local polearm_full_flag = inst.components.hutao_com_polearm_mastery:IsFull()
        -----------------------------------------------------------------------
        --- 伤害结算函数太复杂，单独剥离。
            -- inst:PushEvent("hutao_event.polearm_mastery.do_damage",{
            --     start_pos = start_pos,
            --     end_pos = end_pos,
            -- })
            inst.components.hutao_com_polearm_mastery:SetSpikeCasting(true)
            local targets = inst.components.hutao_com_polearm_mastery:DoSpikeLineTargetSearch(start_pos,end_pos) or {}
            if #targets > 0 then
                inst.components.hutao_com_polearm_mastery:DoSpikeCastingDamage(targets)
            end
            inst.components.hutao_com_polearm_mastery:SetSpikeCasting(false)
        -----------------------------------------------------------------------
        --- 充能
            if not polearm_full_flag then
                inst.components.hutao_com_polearm_mastery:DoDelta(2)
            end
        -----------------------------------------------------------------------
        --- 台词控制器
            inst.components.hutao_com_dialogue:SayWithCD("hutao_com_polearm_mastery.spike",math.random(200)/10)
        -----------------------------------------------------------------------
        --- 连续突刺控制器
            if not TUNING["hutao.Config"].ALLOW_CONTINUOUS_SPIKE then -- 设置里配置是否允许连续突刺
                inst:PushEvent("hutao_event.getting_into_the_running.force_stop") -- 停止奔跑状态
            end
        -----------------------------------------------------------------------
    end
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--- 武器客制化伤害（覆盖）倍增
    --[[
        铲子：（惠飞须泽）胡桃最熟悉的武器，
        手持的时候会自动充能，满充时基础威力会变为12倍，普攻一次后清空充能
        突刺时若满充能则对命中的第一个单位造成相当于基础威力24倍的伤害，然后进入冷却
    ]]
    local function IsShovel(weapon,player)
        -- if weapon and weapon:HasTag("DIG_tool") then
        --     return true
        -- end
        -- if weapon and Shovel_Prefabs[weapon.prefab] then
        --     return true
        -- end
        if weapon and player.components.hutao_com_polearm_mastery 
            and player.components.hutao_com_polearm_mastery:IsShovelWeapon(weapon.prefab) then
            return true
        end
        return false
    end
    local function get_damage_param_replace_fn(weapon,attacker,target,damage,spdamage)
        -- print("get_damage_param_replace_fn",weapon,attacker,target,damage,spdamage)
        if not IsShovel(weapon,attacker) then
            return damage,spdamage
        end
        if attacker.components.hutao_com_polearm_mastery and attacker.components.hutao_com_polearm_mastery:IsFull() then
            if weapon:HasTag("hutao_tag.polearm_spike_casting") then                
                damage = damage*24
            else
                damage = damage*12
            end
        end
        return damage,spdamage
    end
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

return function(inst)
    -------------------------------------------------------
    --- 冲刺完成后，启动长矛指示器
        local indicator_task = nil
        local function indicator_task_fn(inst)
            if IsSpellCanCast(inst) then                
                    -------------------------------------
                    if inst.___polearm_mastery_indicator and inst.___polearm_mastery_indicator:IsValid() then

                    else
                        inst.___polearm_mastery_indicator = CreateIndicator(inst)
                        -- print("create new indicator")
                    end
                    -------------------------------------
            end
        end
        inst:ListenForEvent("hutao_event.client_side.polearm_mastery.spike_create_indicator",function(inst,flag)
            if not IsSpellCanCast(inst) then
                return
            end            
            -- print("fake error hutao_classified_physical_power_running",flag,IsRunning(inst))
            if flag and indicator_task == nil then
                    indicator_task_fn(inst)
                    indicator_task = inst:DoPeriodicTask(0.5,indicator_task_fn)
            elseif flag == false then

                    if indicator_task then
                        indicator_task:Cancel()
                        indicator_task = nil
                    end

                    if inst.___polearm_mastery_indicator and inst.___polearm_mastery_indicator:IsValid() then
                        inst.___polearm_mastery_indicator:Remove()
                        inst.___polearm_mastery_indicator = nil
                    end

            end


        end)
    -------------------------------------------------------
    --- 双重 running 事件判定，减少net 肯能的延迟 造成 无法顺利切换到突刺。
        ----- 通过 hutao_com_physical_power net 来的事件。
        inst:ListenForEvent("hutao_classified_physical_power_running",function(inst,flag)
            -- flag = flag or inst.replica.hutao_com_polearm_mastery:IsRunning()
            local flag = IsRunning(inst)
            inst:PushEvent("hutao_event.client_side.polearm_mastery.spike_create_indicator",flag)
        end)
        ----- 通过 hutao_com_polearm_mastery net 来的事件。
        inst:ListenForEvent("hutao_classified_polearm_mastery_data",function(inst)
            local flag = IsRunning(inst)
            inst:PushEvent("hutao_event.client_side.polearm_mastery.spike_create_indicator",flag)
        end)
    -------------------------------------------------------
    --- 检查是否是服务器
        if not TheWorld.ismastersim then
            return
        end
    -------------------------------------------------------
    --- 添加核心组件
        inst:AddComponent("hutao_com_polearm_mastery") -- 长柄专精控制器+突刺
        inst.components.hutao_com_polearm_mastery:SetMax(12)
        inst:AddComponent("hutao_com_weapon_get_damage_replace") -- 武器伤害覆盖器
        inst.components.hutao_com_weapon_get_damage_replace:SetCustomFn(get_damage_param_replace_fn)
    -------------------------------------------------------
    --- 武器添加
        ---- 可使用【突刺】的武器
        inst.components.hutao_com_polearm_mastery:AddSpikeWeapon("spear")   -- 长矛
        inst.components.hutao_com_polearm_mastery:AddSpikeWeapon("spear_wathgrithr") -- 战斗长矛
        inst.components.hutao_com_polearm_mastery:AddSpikeWeapon("shovel")  -- 铲子
        inst.components.hutao_com_polearm_mastery:AddSpikeWeapon("goldenshovel")    -- 金铲子
        -- inst.components.hutao_com_polearm_mastery:AddSpikeWeapon("pitchfork")    -- 草叉
        -- inst.components.hutao_com_polearm_mastery:AddSpikeWeapon("goldenpitchfork")  -- 金草叉
        inst.components.hutao_com_polearm_mastery:AddSpikeWeapon("trident")  -- 三叉戟
        inst.components.hutao_com_polearm_mastery:AddSpikeWeapon("firestaff")  -- 火魔杖
        inst.components.hutao_com_polearm_mastery:AddSpikeWeapon("icestaff")   -- 冰魔杖
        inst.components.hutao_com_polearm_mastery:AddSpikeWeapon("telestaff")  -- 传送法杖
        inst.components.hutao_com_polearm_mastery:AddSpikeWeapon("nightstick")  -- 晨星锤
        inst.components.hutao_com_polearm_mastery:AddSpikeWeapon("grass_umbrella")  -- 草雨伞
        inst.components.hutao_com_polearm_mastery:AddSpikeWeapon("umbrella")  -- 雨伞
        inst.components.hutao_com_polearm_mastery:AddSpikeWeapon("voidcloth_umbrella")  -- 暗影雨伞
        inst.components.hutao_com_polearm_mastery:AddSpikeWeapon("shovel_lunarplant")  -- 亮茄锄铲
        if TUNING.HUTAO_DEBUGGING_MODE then -- debug期间，允许亮茄剑，测试 位面/阵营伤害
            inst.components.hutao_com_polearm_mastery:AddSpikeWeapon("sword_lunarplant")  -- 亮茄剑
        end
        ---- 铲子类型
        inst.components.hutao_com_polearm_mastery:AddShovelWeapon("shovel")   -- 铲子
        inst.components.hutao_com_polearm_mastery:AddShovelWeapon("goldenshovel")    -- 金铲子
        inst.components.hutao_com_polearm_mastery:AddShovelWeapon("shovel_lunarplant")  -- 亮茄锄铲
    -------------------------------------------------------
    --- 自动增长。任何时候都自动增加。
        inst:DoPeriodicTask(1,function()            
            local mult = inst.components.locomotor:GetSpeedMultiplier()
            local value = 1
            inst.components.hutao_com_polearm_mastery:DoDelta(value*mult)            
        end)
    -------------------------------------------------------
    --- 执行冲刺，RPC来的控制命令。
        inst:ListenForEvent("hutao_event.polearm_mastery.spike_start",function(inst,tarpos)
            if IsSpellCanCast(inst) then
                do_spike_assault_and_damage(inst,tarpos)
                inst.components.hutao_com_physical_power:DoDelta(-SPIKE_COST)
            end            
        end)
    -------------------------------------------------------
    --- 普通攻击充能。【笔记】注意处理突刺期间，是否允许充能。
        inst:ListenForEvent("onhitother",function(inst,_table)
            local target = _table and _table.target
            local weapon = _table and _table.weapon
            local damage = _table and _table.damage or 0
            if target and damage > 0 and (weapon == nil or not weapon:HasTag("hutao_spell_hidden_weapon")) then -- target.brainfn and target.sg and
                -- tag:hutao_spell_hidden_weapon 用来给上debuff 的武器做区分屏蔽。比如隐藏的冰魔杖/火魔杖
                if not inst.components.hutao_com_polearm_mastery:IsFull() and 
                    not inst.components.hutao_com_polearm_mastery:IsSpikeCasting() then
                    inst.components.hutao_com_polearm_mastery:DoDelta(1)
                else
                    if IsShovel(weapon,inst) then
                        inst.components.hutao_com_polearm_mastery:Clear()
                    end
                end
            end
        end)
    -------------------------------------------------------

end